local skynet = require 'skynet'
local utils = require "utils"
local reason = require "reason"
local error_code = require "error_code"
local constant = require "constant"
local data_access = require "data_access"
local table_def = require "table_def"
local game_def = require "game_def"
local cjson = require "cjson"

local table_insert = table.insert
local table_sort = table.sort
local math_floor = math.floor
local math_round = math.round

local BASE_DATA_MAP = {
    [constant.ITEM_COIN_ID] = true,
    [constant.ITEM_GEM_ID] = true,
    [constant.ITEM_ROOMCARD_ID] = true,
    [constant.ITEM_CNOTE_ONE_ID] = true,
    [constant.ITEM_CNOTE_TWO_ID] = true,
    [constant.ITEM_CNOTE_THREE_ID] = true,
    [constant.ITEM_JIABEICARD_ID] = true,
}

local function intercept_url(url,data)
    if url == '/api/v1/onebyone/withdraw' then
        local request = cjson.decode(data)
        local uid = player.uid
        --local withdrawAmount = request.withdrawAmount * 100

        local ok, ret = R().basesvr({key=uid}):call('.msg_handler', 'check_exchange', uid,request.withdrawAmount)
        if not ok or not ret then
            ERR(url, "get coins fail")
            return false, cjson.encode({code = -11, msg = "申请异常，请联系客户", result = {}})
        end
        if ret == 1 then
            return false, cjson.encode({code = -14, msg = "可兑换金币不足", result = {}})
        end
        if ret == 2 then
            return false, cjson.encode({code = -13, msg = "尚有流水未完成", result = {}})
        end
        local ok,table_gid = R().exdbsvr(1):call('.tlock_mgr','get_player_table',uid)
        if not ok then
            ERR(url,'get player table fail')
            return false, cjson.encode({code = -11, msg = "申请异常，请联系客户", result = {}})
        end
        if table_gid and table_gid > 0 then
            return false, cjson.encode({code = -12, msg = "正在对局中无法进行提现，请耐心等待对局结束", result = {}})
        end
    end
    return true
end

local function intercept_ret_url(url,body)
    if url == '/api/v1/onebyone/user_info' then
        local tb_body = cjson.decode(body)
        local uid = player.uid
        --errlog(tostring_r(tb_body))
        local ok, ret = R().basesvr({key=uid}):call('.msg_handler', 'get_exchange_need_water', uid)
        if ok and ret and tb_body.result.money_val then
            if tb_body.result.money_val[1] then
                tb_body.result.money_val[1].exchange_need_water = math_floor(ret)
            end

            if tb_body.result.money_val[2] then
                tb_body.result.money_val[2].exchange_need_water = math_floor(ret)
            end
        end
        body = cjson.encode(tb_body)
        return true,body
    end
    if url == '/api/v1/onebyone/bingding' then --绑定银行支付宝时把名字改下      
        local tb_body = cjson.decode(body)        
        local name = tb_body.result.name
        dbglog("__绑定银行支付宝时把名字改下__bingding_", tb_body, name)  
        if name then
            player.user_data.name = name
            send_to_gateway('hall.NTF_USER_PRO',{info = {name=name}})
        end      
        return true,body
    end
    return true
end

local function common_post(url, data, is_shisun)
    local ret, body = intercept_url(url,data)
    if not ret then
        return 200, body
    end
    local uid, last_login_ip, channel, client_version, device_brand, device_id, os_system, platform,current_system
    if player then
        uid = player.uid
        last_login_ip = player.user_data.last_login_ip
        channel = player.channel
        client_version = player.client_version
        device_brand = player.device_brand
        device_id = player.device_id
        account_id = player.account_id
        os_system = player.user_data.os_system --注册客户端系统
        platform = player.user_data.platform
        current_system = player.os_system -- 客户端当前系统
    end
    local exheader = {
        uid = uid,
        ip = last_login_ip,
        channel = channel,
        client_version = client_version,
        device_brand = device_brand,
        device_id = device_id,
        account_id = account_id,
        os_system = os_system,
        platform = platform,
        current_system = current_system,
    }
    dbglog(url,data, exheader)
    local ok,status,body = R().accountsvr({rand=true}):call('.web_proxy','web_post',url, data, exheader, is_shisun)
    if not ok then
        errlog(url,'failed to common_post========',uid,status,tostring_r(body))
        return -1
    end

    local ok,new_body = intercept_ret_url(url,body)

    if ok and new_body then
        return status,new_body
    end

    return status,body
end

local function in_white_list(uid,white_list)
    for _,white_uid in pairs(white_list) do
        if uid == white_uid then
            return true
        end
    end
    return false
end

--[[
    验证一下炸金花开房参数是否正确
]]
local function check_zhajinhua_ftable_conf(uid,table_type,create_conf)
    local count = create_conf.total_count
    local dizhu = create_conf.dizhu
    local dingzhu = create_conf.dingzhu
    local max_bet_round = create_conf.max_bet_round
    local comparable_bet_round = create_conf.comparable_bet_round
    local max_look_round = create_conf.max_look_round
    local play_num = create_conf.play_num

    local friendroomdata = global_configs.friendroomdata[table_type]
    if not friendroomdata then
        return false
    end

    --如果是俱乐部金币私人场 如果检查
    print(tostring_r(friendroomdata))
    if friendroomdata.cost_type and friendroomdata.cost_type > 0 then
        if friendroomdata.white_list then
            --判断白名单
            local while_list = utils.str_split(friendroomdata.while_list,',')
            if in_white_list(uid,while_list) then
                if dizhu > friendroomdata.max_white_dizhu or dizhu < friendroomdata.min_white_dizhu then
                    errlog("dizhu > friendroomdata.max_white_dizhu and dizhu < friendroomdata.min_white_dizhu",dizhu,friendroomdata.max_white_dizhu,friendroomdata.min_white_dizhu)
                    return false
                end
            end
        else
            errlog(tostring_r(create_conf))
            if dizhu > friendroomdata.max_dizhu or dizhu < friendroomdata.min_dizhu then
                errlog("dizhu > friendroomdata.max_dizhu and dizhu < friendroomdata.min_dizhu",dizhu,friendroomdata.max_dizhu,friendroomdata.min_dizhu)
                return false
            end

            --金币场需要检查游戏时长 30到360分钟
            if create_conf.game_time < constant.ZJH_MIN_GAME_TIME or create_conf.game_time > constant.ZJH_MAX_GAME_TIME then
                errlog("create_conf.game_time < 30 or create_conf.game_time > 360",create_conf.game_time)
                return false
            end

            --最少携带金币必须是1个底注
            if create_conf.min_need_money < dizhu then
                errlog("create_conf.min_need_money < dizhu*20",create_conf.min_need_money)
                return false
            end

            if create_conf.max_need_money > friendroomdata.max_need_money then
                errlog("create_conf.max_need_money > friendroomdata.max_need_money",create_conf.max_need_money,friendroomdata.max_need_money)
                return false
            end

            if create_conf.max_need_money > dizhu*10000 then
                errlog("create_conf.max_need_money > dizhu*200",create_conf.max_need_money,dizhu*10000)
                return false
            end

            --金币场私人房需要检查最少最大携带
            if create_conf.max_need_money < dizhu*100 then
                errlog("create_conf.max_need_money < dizhu*100",create_conf.max_need_money,dizhu*100)
                return false
            end

            --最大顶注检测
            if dingzhu < friendroomdata.min_ration*dizhu or dingzhu > create_conf.max_need_money then
                errlog("dingzhu < friendroomdata.min_ration*dizhu or dingzhu > create_conf.max_need_money",dingzhu,dizhu)
                return false
            end
        end
    else
        -- 检验一下玩家的局数输入是否是10的倍数
        if count % 10 ~= 0 then
            errlog("count % 10 ~= 0",count)
            return false
        end
    
        -- 检验一下设置是否超过了最大局数
        if count > friendroomdata.max_count or count <= 0 then
            errlog("count > friendroomdata.max_count or count <= 0",count,friendroomdata.max_count)
            return false
        end

        --检查底注是否符合范围
        if dizhu > friendroomdata.max_dizhu or dizhu < friendroomdata.min_dizhu then
            errlog("dizhu > friendroomdata.max_dizhu and dizhu < friendroomdata.min_dizhu",dizhu,friendroomdata.max_dizhu,friendroomdata.min_dizhu)
            return false
        end

        --检查顶注配置
        if dingzhu < friendroomdata.min_ration*dizhu or dingzhu > friendroomdata.max_ration*dizhu then
            errlog("dingzhu < friendroomdata.min_ration*dizhu or dingzhu > friendroomdata.max_ration*dizhu",dingzhu,dizhu)
            return false
        end
    end

    if max_bet_round > comparable_bet_round then
        errlog("max_bet_round > comparable_bet_round",max_bet_round,comparable_bet_round)
        return false
    end

    if max_bet_round > friendroomdata.max_bet_round then
        errlog("max_bet_round > friendroomdata.max_bet_round",max_bet_round,friendroomdata.max_bet_round)
        return false
    end

    if comparable_bet_round > friendroomdata.comparable_bet_round then
        errlog("comparable_bet_round > friendroomdata.max_bet_round",comparable_bet_round,friendroomdata.comparable_bet_round)
        return false
    end

    if max_look_round > friendroomdata.max_look_round then
        errlog("max_look_round > friendroomdata.max_look_round",max_look_round,friendroomdata.max_look_round)
        return false
    end

    --检测人数配置是否正确
     if not create_conf.is_creator_start then
        if create_conf.least_num < 2 then
            errlog("create_conf.least_num",create_conf.least_num)
            return false
        end

        local play_num_list = utils.str_split(friendroomdata.play_num,',')
        print(tostring_r(play_num_list))
        local is_find = false
        for _,num in pairs(play_num_list) do
            if tonumber(num) == play_num then 
                is_find = true
                break
            end
        end
        if not is_find then
            errlog("play_num is error",play_num)
            return false
        end

        if play_num == constant.ZJH_MIN_PLAY_NUM then
            if create_conf.least_num > play_num or create_conf.least_num < 2 then
                errlog("create_conf.least_num > play_num or create_conf.least_num < 2",play_num,create_conf.least_num)
                return false
            end
        elseif play_num == constant.ZJH_MAX_PLAY_NUM then
            if create_conf.least_num > play_num or create_conf.least_num < 5 then
                errlog("create_conf.least_num > play_num or create_conf.least_num < 5",play_num,create_conf.least_num)
                return false
            end
        else
            return false
        end
    end

    return true
end

--[[
    获取需要扣除的房卡数
]]
local function check_create_table_config(uid,table_type,is_aa,count)
    local room_data = global_configs.friendroomdata[table_type]

    if not room_data then
        return error_code.FRIENDROOMDATA_CONFIG_ERROR
    end

    local multiple = math_floor(count / 10)

    local cost = nil
    if is_aa then
        cost = room_data.aa_cost * multiple
    else
        cost = room_data.cost * multiple
    end

    if not cost then
        errlog(uid,'cost config is error')
        return error_code.FRIENDROOMDATA_CONFIG_ERROR
    end

    -- 向baseserver查询玩家房卡是否足够
    local ok,able = R().basesvr({key=uid}):call('.msg_handler','can_reduce_roomcards',uid,cost)
    if not ok then
        errlog(uid,'failed to can_reduce_roomcards',cost)
        return
    end

    if not able then
        return error_code.ROOMCARD_IS_NOT_ENOUGH
    end

    return 0,cost
end

--[[
    创建好友桌子 根据不同的类型创建不同的create_data
]]
local function make_ftable_create_data(table_type,cost,msg)
    local zhajinhua_create_conf = msg.zhajinhua_create_conf
    if zhajinhua_create_conf then
        local create_data = {
            table_type = table_type,
            cost = cost,
            total_count = zhajinhua_create_conf.total_count,
            dizhu = zhajinhua_create_conf.dizhu,
            dingzhu = zhajinhua_create_conf.dingzhu,
            max_bet_round = zhajinhua_create_conf.max_bet_round,
            comparable_bet_round = zhajinhua_create_conf.comparable_bet_round,
            is_authorized_seat = zhajinhua_create_conf.is_authorized_seat,
            is_aa = zhajinhua_create_conf.is_aa,
            max_look_round = zhajinhua_create_conf.max_look_round,
            play_num = zhajinhua_create_conf.play_num,
            min_need_money = zhajinhua_create_conf.min_need_money,
            max_need_money = zhajinhua_create_conf.max_need_money,
            is_creator_start = zhajinhua_create_conf.is_creator_start,
            least_num = zhajinhua_create_conf.least_num,
            game_time = zhajinhua_create_conf.game_time,
            club_id = zhajinhua_create_conf.club_id,
            table_name = zhajinhua_create_conf.table_name,
        }
        return create_data
    end
end

local function notify_money_changed(uid,chged,reason)
    local ntf={}
    local flags = 0

    if chged.coins then
        ntf.coins = chged.coins
        flags = flags | (1 << 0)
    end

    if chged.gems then
        ntf.gems = chged.gems
        flags = flags | (1 << 1)
    end

    if chged.roomcards then
        ntf.roomcards = chged.roomcards
        flags = flags | (1 << 2)
    end

    ntf.flags = flags
    ntf.reason = reason
    send_to_gateway('hall.NTF_USER_MONEY',ntf)
    return true
end

local function check_match_table_config(table_type)
    local uid = player.uid 
    local roomdata = global_configs.roomdata
    if not roomdata[table_type] then
        return -99
    end

    --由这边先去判断下是否已经被桌定在桌子上了
    local ok,table_gid = R().exdbsvr(1):call('.tlock_mgr','get_player_table',uid)
    if not ok then
        errlog(uid,'failed to get_player_table')
        return error_code.FAILED_TO_MATCH_PLAYER
    end

    if table_gid ~= 0 then
        local tsvr_id = utils.extract_table_gid(table_gid)
        local dest = R().tablesvr(tsvr_id):dest()
        return error_code.PLAYER_IS_ON_TABLE,dest,table_gid
    end

    local ok,base_data = R().basesvr({key=uid}):call('.msg_handler','get_base_data',uid)
    if not ok then
        errlog(uid,'failed to get base_data',uid)
        return -1000
    end
    -- player.base_data = base_data

    --红包扫雷没有限制
    if not roomdata[table_type].min then
        return 0
    end

    if base_data.coins < roomdata[table_type].min then
        return error_code.GOLD_IS_NOT_ENOUGH_STRING,roomdata[table_type].min
    end

    if roomdata[table_type].max == 0 then
        return 0
    else
        if base_data.coins > roomdata[table_type].max then
            return error_code.GOLD_OUT_OF_MAX
        end
    end

   return 0
end

local function notify_user_money(player)
    local user_data = player.user_data
    local ntf={
        coins = user_data.coins,
        gems = user_data.gems,
        roomcards = user_data.roomcards,
    }

    send_to_gateway('hall.NTF_USER_MONEY',ntf)
    return true
end

local function add_awards(uid,award_list,reason)
    local base_data_list = {}
    
    for _,award_info in ipairs(award_list) do
        local award_id = award_info.id
        if BASE_DATA_MAP[award_id] then
            table_insert(base_data_list,award_info)
        end
    end

    local ok,succ,base_data = R().basesvr{key=uid}:call('.msg_handler','add_item_list',
        uid,base_data_list,reason)
    if not ok or not succ then
        errlog(uid,'failed to add item list',tostring_r(base_data_list),base_data)
        return
    end

    if base_data then
        local chged = {
            coins = base_data.coins,
            gems = base_data.gems,
            roomcards = base_data.roomcards,
        }
        return chged
    end
end



local modules = {}

local function register_module_handlers(module,handlers)
    assert(not modules[module])
    modules[module] = handlers
end

local function get_module_handlers(module)
    return modules[module]
end

--拓展模块的函数
local function register_module_handlers_ex(module,handlers)
    assert(modules[module])
    for k, v in pairs(handlers) do 
        if type(v) == "function" then 
            modules[module][k] = v
        end
    end
end

--------------------------------------------------------------------
local M = {
    BASE_DATA_MAP = BASE_DATA_MAP,
    add_awards = add_awards,
    check_match_table_config = check_match_table_config,
    notify_money_changed = notify_money_changed,
    notify_user_money = notify_user_money,

    register_module_handlers = register_module_handlers,
    register_module_handlers_ex = register_module_handlers_ex,
    get_module_handlers = get_module_handlers,
    check_zhajinhua_ftable_conf = check_zhajinhua_ftable_conf,
    make_ftable_create_data = make_ftable_create_data,
    check_create_table_config = check_create_table_config,
    common_post = common_post,

 
}

return M
